package com.aruba.recyclerviewapplication;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;

/**
 * 解决嵌套RecyclerView滑动问题
 */
public class BetterRecyclerView extends RecyclerView {
    private int mTouchSlop;
    private int mScrollPointerId = 0;
    private int mInitialTouchX;
    private int mInitialTouchY;
    private boolean mDisallowIntercept = true;

    public BetterRecyclerView(@NonNull Context context) {
        this(context, null);
    }

    public BetterRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BetterRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        final ViewConfiguration vc = ViewConfiguration.get(context);
        mTouchSlop = vc.getScaledTouchSlop();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        //仿造源码
        final int action = MotionEventCompat.getActionMasked(e);
        final int actionIndex = MotionEventCompat.getActionIndex(e);

        switch (action) {
            case MotionEvent.ACTION_DOWN://记录按下的坐标
                mScrollPointerId = e.getPointerId(0);
                mInitialTouchX = (int) (e.getX() + 0.5f);
                mInitialTouchY = (int) (e.getY() + 0.5f);
                break;
            case MotionEvent.ACTION_POINTER_DOWN://这边处理多手指触摸，优先使用后面触摸的手指
                mScrollPointerId = e.getPointerId(actionIndex);
                mInitialTouchX = (int) (e.getX() + 0.5f);
                mInitialTouchY = (int) (e.getY() + 0.5f);
                break;
            case MotionEvent.ACTION_MOVE://仿造源码
                final int index = e.findPointerIndex(mScrollPointerId);
                final int x = (int) (e.getX(index) + 0.5f);
                final int y = (int) (e.getY(index) + 0.5f);

                boolean startScroll = false;
                if (getScrollState() != SCROLL_STATE_DRAGGING) {
                    final int dx = x - mInitialTouchX;
                    final int dy = y - mInitialTouchY;

                    //这边增加拦截的难度，当滑动的水平距离大于滑动的垂直距离时，才拦截，当然了，如果自身又能竖直滑动的情况，就不判断两个滑动距离大小
                    if ((getLayoutManager().canScrollHorizontally() && Math.abs(dx) > mTouchSlop)
                            && (getLayoutManager().canScrollVertically() || Math.abs(dx) > Math.abs(dy))) {
                        if (mDisallowIntercept) {
                            startScroll = false;
                        } else {
                            startScroll = true;
                        }
                    }
                    //这里是当滑动的水平距离小于滑动的垂直距离时，才拦截，如果自身又能水平滑动的情况，就不判断两个滑动距离大小
                    if ((getLayoutManager().canScrollVertically() && Math.abs(dy) > mTouchSlop)
                            && (getLayoutManager().canScrollHorizontally() || Math.abs(dy) > Math.abs(dx))) {
                        startScroll = true;
                    }
                }
                return startScroll && super.onInterceptTouchEvent(e);
        }

        return super.onInterceptTouchEvent(e);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        final int action = MotionEventCompat.getActionMasked(e);
        if (action == MotionEvent.ACTION_UP)
            mDisallowIntercept = true;
        return super.onTouchEvent(e);
    }

    /**
     * 这个接口是不允许父类打断这个onTouch事件，一般被子类调用getParent.requestDisallowInterceptTouchEvent(true)
     * 比如快速水平滑动子view的时候，这时我们想去竖直滑动父类，因为快速滑动有一个速度，子view还没停止滚动，所以子类禁止父类拦截
     * 想要解决这个办法，就把这个方法改为空方法就行了
     *
     * @param disallowIntercept
     */
    @Override
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        mDisallowIntercept = disallowIntercept;
    }
}
